package com.allin.mall.common.core.json;

import com.google.gson.Gson;
import jakarta.annotation.Resource;
import org.reactivestreams.Publisher;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.MediaType;
import org.springframework.http.codec.HttpMessageEncoder;
import org.springframework.util.MimeType;
import reactor.core.publisher.Flux;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

public class GsonEncoder implements HttpMessageEncoder<Object> {

    private final Gson gson;

    public GsonEncoder(Gson gson) {
        this.gson = gson;
    }

    @Override
    public List<MediaType> getStreamingMediaTypes() {
        return List.of(MediaType.APPLICATION_JSON);
    }

    @Override
    public boolean canEncode(ResolvableType elementType, MimeType mimeType) {
        return mimeType == null || mimeType.includes(MediaType.APPLICATION_JSON);
    }

    @Override
    public Flux<DataBuffer> encode(Publisher<?> inputStream, DataBufferFactory bufferFactory, ResolvableType elementType, MimeType mimeType, Map<String, Object> hints) {
        return Flux.from(inputStream)
                .map(value -> {
                    byte[] bytes = gson.toJson(value).getBytes(StandardCharsets.UTF_8);
                    DataBuffer buffer = bufferFactory.allocateBuffer(bytes.length);
                    buffer.write(bytes);
                    return buffer;
                });
    }

    @Override
    public List<MimeType> getEncodableMimeTypes() {
        return List.of(MediaType.APPLICATION_JSON);
    }
}
